home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / dbg / ds3100.md / dbgMainDbx.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  15KB  |  608 lines

  1. /* dbgMain.c -
  2.  *
  3.  *    This contains the routines which read and execute commands from kdbx.
  4.  *
  5.  *    Copyright (C) 1989 Digital Equipment Corporation.
  6.  *    Permission to use, copy, modify, and distribute this software and
  7.  *    its documentation for any purpose and without fee is hereby granted,
  8.  *    provided that the above copyright notice appears in all copies.  
  9.  *    Digital Equipment Corporation makes no representations about the
  10.  *    suitability of this software for any purpose.  It is provided "as is"
  11.  *    without express or implied warranty.
  12.  */
  13.  
  14. #ifndef lint
  15. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dbg/ds3100.md/dbgMainDbx.c,v 1.1 91/08/02 17:39:12 jhh Exp $ SPRITE (Berkeley)";
  16. #endif not lint
  17.  
  18. #include <sprite.h>
  19. #include <dbgDbxInt.h>
  20. #include <dbgInt.h>
  21. #include <mach.h>
  22. #include <machConst.h>
  23. #include <proc.h>
  24. #include <vm.h>
  25. #include <vmMach.h>
  26. #include <machMon.h>
  27. #include <net.h>
  28. #include <netEther.h>
  29. #include <netInet.h>
  30. #include <dev.h>
  31. #include <sys.h>
  32. #include <sync.h>
  33. #include <main.h>
  34.  
  35. static unsigned sstepInst;            /* The instruction that was
  36.                          * replaced when we tried to
  37.                          * single step. */
  38. static char requestBuffer[DBG_MAX_REQUEST_SIZE + 2];/* Buffer to receive request
  39.                          * into. */
  40. static char *requestBufPtr = requestBuffer + 2;    /* Offset the buffer by 2 so
  41.                          * we four byte align the 
  42.                          * data in the packet. */
  43. static char replyBuffer[DBG_MAX_REPLY_SIZE + 2];/* Buffer to hold reply. */
  44. static char *replyBufPtr = replyBuffer + 2;    /* Offset the buffer by 2 so
  45.                          * we four byte align the 
  46.                          * data in the packet. */
  47.  
  48.  
  49. /*
  50.  * Size of debugging packet header and data.
  51.  */
  52. #define    PACKET_HDR_SIZE (sizeof(Net_EtherHdr) + Dbg_PacketHdrSize())
  53. #define PACKET_DATA_SIZE \
  54.     (DBG_MAX_REPLY_SIZE - PACKET_HDR_SIZE - sizeof(Dbg_Reply) + 4)
  55.  
  56. /*
  57.  * Message buffers.
  58.  */
  59.  
  60. static Dbg_Request    *requestPtr;
  61. static Dbg_Reply    *replyPtr;
  62. static char        *dataPtr;
  63.  
  64. /*
  65.  * Strings which describe each of the opcodes that kdbx can send us.
  66.  */
  67. static char *opcodeNames[] =  {
  68.     "Unknown",
  69.     "IREAD",
  70.     "DREAD",
  71.     "UREAD",
  72.     "IWRITE",
  73.     "DWRITE",
  74.     "UWRITE",
  75.     "CONTP",
  76.     "PKILL",
  77.     "SSTEP",
  78.     "Unknown",
  79.     "Unknown",
  80.     "Unknown",
  81.     "Unknown",
  82.     "DBREAD",
  83.     "DBWRITE",
  84.     "DHREAD",
  85.     "DHWRITE",
  86.     "QUERY",
  87.     "BEGINCALL",
  88.     "ENDCALL",
  89.     "DETACH",
  90.     "GETMAXSTACK",
  91.     "GETSTATUS",
  92. };
  93.  
  94. /*
  95.  * Strings which describe the different exceptions that can occur.
  96. */
  97. static char *exceptionNames[] = {
  98.     "Interrupt",
  99.     "TLB Mod",
  100.     "TLB LD miss",
  101.     "TLB ST miss",
  102.     "TLB load address error",
  103.     "TLB store address error",
  104.     "TLB ifetch bus error",
  105.     "TLB load or store bus error",
  106.     "System call",
  107.     "Breakpoint trap",
  108.     "Reserved instruction",
  109.     "Coprocessor unusable",
  110.     "Overflow"
  111. };
  112.  
  113. /*
  114.  * Declare global variables.
  115.  */
  116. extern int            dbgTermReason;
  117. extern int            dbgInDebugger;
  118. extern int            dbgIntPending;
  119. extern Boolean            dbgPanic;
  120. extern int            dbgMaxStackAddr;
  121. extern Boolean            dbg_UsingSyslog;
  122. extern Boolean            dbgCanUseSyslog;
  123. extern int            dbgPacketLength;
  124. extern Net_InetAddress        dbgMyIPAddr;
  125. extern Net_InetAddress        dbgSrcIPAddr;
  126. extern Net_InetAddress        dbgSrcPort;
  127. extern Net_EtherHdr        dbgEtherHdr;
  128. extern Net_ScatterGather    dbgGather;
  129. extern Net_Interface        *dbgInterPtr;
  130. extern int            dbgTimeout;
  131. extern unsigned            dbgTLB[VMMACH_NUM_TLB_ENTRIES][2];
  132. extern Boolean            dbgGotPacket;
  133.  
  134. /*
  135.  * Trap causes (same numbering as in ptrace.h).
  136.  */
  137. #define CAUSE_SINGLE    4
  138. #define CAUSE_BREAK    5
  139.  
  140. /*
  141.  * Trap instruction.
  142.  */
  143. #define SSTEP_INST    (MACH_SSTEP_VAL | 0xd)
  144.  
  145. Boolean    dbg_OthersCanUseNetwork = TRUE;
  146.  
  147. /* 
  148.  * Forward declarations:
  149.  */
  150.  
  151. static char *    TranslateOpcode _ARGS_((int opcode));
  152. static char *    TranslateException _ARGS_((int exception));
  153. static Boolean    ReadRequest _ARGS_((Boolean timeout));
  154. static void    SendReply _ARGS_((int dataSize));
  155.  
  156.  
  157. /*
  158.  * ----------------------------------------------------------------------------
  159.  *
  160.  * TranslateOpcode --
  161.  *
  162.  *     Return the string which describes the given opcode.
  163.  *
  164.  * Results:
  165.  *     Pointer to the string which describes the given opcode.
  166.  *
  167.  * Side effects:
  168.  *     None.
  169.  *
  170.  * ----------------------------------------------------------------------------
  171.  */
  172. static char *
  173. TranslateOpcode(opcode)
  174.     int opcode;        /* The opcode which is to be translated. */
  175. {
  176.     int index;
  177.  
  178.     index = (int) opcode;
  179.     if (index < 0 || index >= sizeof(opcodeNames) / 4) {
  180.         index = 0;
  181.     }
  182.  
  183.     return(opcodeNames[index]);
  184. }
  185.  
  186.  
  187. /*
  188.  * ----------------------------------------------------------------------------
  189.  *
  190.  * TranslateException --
  191.  *
  192.  *     Return the string that describes the given exception.
  193.  *
  194.  * Results:
  195.  *     Pointer to string which describes the given exception.
  196.  *
  197.  * Side effects:
  198.  *     None.
  199.  *
  200.  * ----------------------------------------------------------------------------
  201.  */
  202. static char *
  203. TranslateException(exception)
  204.     int exception;        /* The exception which is to be translated. */
  205. {
  206.  
  207.     if (exception < 0 || exception > MACH_EXC_OVFLOW) {
  208.         return("Unknown");
  209.     } else {
  210.         return(exceptionNames[exception]);
  211.     }
  212. }
  213.  
  214.  
  215. /*
  216.  * ----------------------------------------------------------------------------
  217.  *
  218.  * Dbg_DbxInit --
  219.  *
  220.  *     Initialize the kdbx aspects of the debugger.
  221.  *
  222.  * Results:
  223.  *     None.
  224.  *
  225.  * Side effects:
  226.  *     Global variables are initialized.
  227.  *
  228.  * ----------------------------------------------------------------------------
  229.  */
  230. void
  231. DbgDbxInit()
  232. {
  233.     dbgMaxStackAddr = (int)mach_StackBottom + mach_KernStackSize;
  234.     replyPtr = (Dbg_Reply *)(replyBufPtr + PACKET_HDR_SIZE);
  235.     dataPtr = replyBufPtr + PACKET_HDR_SIZE + sizeof(Dbg_Reply) - 4;
  236. }
  237.  
  238.  
  239. /*
  240.  * ----------------------------------------------------------------------------
  241.  *
  242.  * DbgDbxStoreRequest --
  243.  *
  244.  *     Put the request into the request buffer.
  245.  *
  246.  * Results:
  247.  *     None.
  248.  *
  249.  * Side effects:
  250.  *     Stuff is put into requestBuffer.
  251.  *
  252.  * ----------------------------------------------------------------------------
  253.  */
  254.  
  255. void 
  256. DbgDbxStoreRequest(size, reqPtr)
  257.     int        size;
  258.     char    *reqPtr;
  259. {
  260.     if (dbgTraceLevel >= 4) {
  261.     Mach_MonPrintf("DbgDbxStoreRequest\n");
  262.     }
  263.     bcopy(reqPtr, requestBuffer, size);
  264.     requestPtr = (Dbg_Request *)requestBuffer;
  265. }
  266.  
  267. /*
  268.  * ----------------------------------------------------------------------------
  269.  *
  270.  * ReadRequest --
  271.  *
  272.  *     Read the next request from kdbx.
  273.  *
  274.  * Results:
  275.  *     None.
  276.  *
  277.  * Side effects:
  278.  *     TRUE if didn't time out.
  279.  *
  280.  * ----------------------------------------------------------------------------
  281.  */
  282. static Boolean
  283. ReadRequest(timeout)
  284.     Boolean    timeout;    /* TRUE if should timeout after waiting a 
  285.                  * while. */
  286. {
  287.     int            timeOutCounter;
  288.     Net_Interface    *interPtr;
  289.     int            i;
  290.  
  291.     dbgGotPacket = FALSE;
  292.     if (dbgTraceLevel >= 4) {
  293.     Mach_MonPrintf("ReadRequest\n");
  294.     }
  295.     timeOutCounter = dbgTimeout;
  296.     do {
  297.     /*
  298.      * Listen on all the interfaces. The debugger is relatively
  299.      * stateless so its easiest to just listen on them all.
  300.      */
  301.     for (i = 0; ; i++) {
  302.         interPtr = Net_NextInterface(TRUE, &i);
  303.         if (interPtr == (Net_Interface *) NIL) {
  304.         break;
  305.         }
  306.         Net_RecvPoll(interPtr);
  307.         if (dbgGotPacket) {
  308.         break;
  309.         }
  310.     }
  311.     if (timeout) {
  312.         timeOutCounter--;
  313.     }
  314.     } while(!dbgGotPacket && timeOutCounter != 0);
  315.     if (dbgGotPacket) {
  316.     requestPtr = (Dbg_Request *)requestBuffer;
  317.     if (dbgTraceLevel >= 4) {
  318.         Mach_MonPrintf("MsgNum = %d\n", requestPtr->num);
  319.     }
  320.     }
  321.  
  322.     return(dbgGotPacket);
  323. }
  324.  
  325.  
  326. /*
  327.  * ----------------------------------------------------------------------------
  328.  *
  329.  * SendReply --
  330.  *
  331.  *     Send a reply to kdbx.
  332.  *
  333.  * Results:
  334.  *     None.
  335.  *
  336.  * Side effects:
  337.  *     None.
  338.  *
  339.  * ----------------------------------------------------------------------------
  340.  */
  341. static void
  342. SendReply(dataSize)
  343.     int    dataSize;
  344. {
  345.     Net_EtherHdr        *etherHdrPtr;
  346.  
  347.     replyPtr->num = requestPtr->num;
  348.  
  349.     if (dbgTraceLevel >= 4) {
  350.     Mach_MonPrintf("Sending reply %d\n", replyPtr->num);
  351.     }
  352.     etherHdrPtr = (Net_EtherHdr *) replyBufPtr;
  353.     etherHdrPtr->source = dbgEtherHdr.destination;
  354.     etherHdrPtr->destination = dbgEtherHdr.source;
  355.     etherHdrPtr->type = dbgEtherHdr.type;
  356.     dbgGather.bufAddr = replyBufPtr + sizeof(Net_EtherHdr);
  357.     dbgGather.length = PACKET_HDR_SIZE + sizeof(Dbg_Reply) + dataSize - 
  358.                sizeof(Net_EtherHdr);
  359.     dbgGather.mutexPtr = (Sync_Semaphore *) NIL;
  360.     Dbg_FormatPacket(dbgMyIPAddr, dbgSrcIPAddr, dbgSrcPort,
  361.              dataSize + sizeof(Dbg_Reply),
  362.              replyBufPtr + sizeof(Net_EtherHdr));
  363.     Net_RawOutput(dbgInterPtr, etherHdrPtr, &dbgGather, 1);
  364.     if (dbgTraceLevel >= 4) {
  365.     Mach_MonPrintf("Sent reply\n");
  366.     }
  367. }
  368.  
  369. /*
  370.  * Whether syslog should remain diverted on continue or not.
  371.  */
  372. static Boolean    syslogDiverted = FALSE;
  373.  
  374. extern Mach_DebugState    mach_DebugState;
  375.  
  376. static Mach_DebugState    tmpDebugState;
  377. static Mach_DebugState    *debugStatePtr;
  378.  
  379.  
  380. /*
  381.  * ----------------------------------------------------------------------------
  382.  *
  383.  * Dbg_Main --
  384.  *
  385.  *     The main debugger loop.  This will read commands from the network
  386.  *     and call the proper routine to execute them.
  387.  *
  388.  * Results:
  389.  *     None.
  390.  *
  391.  * Side effects:
  392.  *     None.
  393.  *
  394.  * ----------------------------------------------------------------------------
  395.  */
  396. unsigned
  397. Dbg_DbxMain()
  398. {
  399.     Boolean    done;
  400.     Boolean    atInterruptLevel;
  401.     unsigned    cause;
  402.     int        signal;
  403.     int        origSignal;
  404.     int        dataSize;
  405.     int        origMaxStackAddr;
  406.  
  407.     origMaxStackAddr = dbgMaxStackAddr;
  408.     debugStatePtr = &mach_DebugState;
  409.  
  410.     if (dbg_BeingDebugged) {
  411.  
  412.     SendReply(0);
  413.     do {
  414.         if (ReadRequest(TRUE)) {
  415.         if (requestPtr->request == DBG_GETSTATUS) {
  416.             break;
  417.         }
  418.         }
  419.         Net_RawOutput(dbgInterPtr, (Net_EtherHdr *)replyBuffer, 
  420.             &dbgGather, 1);
  421.         Mach_MonPrintf("TI: %d ", requestPtr->request);
  422.     } while (TRUE);
  423.     } 
  424.  
  425.     Vm_MachDumpTLB(dbgTLB);
  426.  
  427.     done = FALSE;
  428.     while (!done) {
  429.     int    request;
  430.  
  431.     dataSize = 0;
  432.     replyPtr->status = 1;
  433.     replyPtr->data = 0;
  434.     request = requestPtr->request;
  435.     if (dbgTraceLevel >= 1) {
  436.         Mach_MonPrintf("Request: %d, %s at %x\n", request, 
  437.             TranslateOpcode(request), requestPtr->addr);
  438.     }
  439.     switch (request) {
  440.             case DBG_UREAD:
  441.         if (requestPtr->addr > sizeof(mach_DebugState) / 4) {
  442.             Mach_MonPrintf("Bogus UREAD addr %x\n", requestPtr->addr);
  443.             replyPtr->status = 0;
  444.         } else {
  445.             replyPtr->data = *((int *)debugStatePtr + requestPtr->addr);
  446.         }
  447.         break;
  448.             case DBG_UWRITE: {
  449.         extern void Mach_SwitchPoint();    /* XXX - should go elsewhere */
  450.  
  451.         if (requestPtr->addr == (unsigned)-1) {
  452.             Proc_ControlBlock    *procPtr;
  453.  
  454.             if (requestPtr->data == 0) {
  455.             debugStatePtr = &mach_DebugState;
  456.             signal = origSignal;
  457.             dbgMaxStackAddr = origMaxStackAddr;
  458.             break;
  459.             } else {
  460.             procPtr = Proc_GetPCB(requestPtr->data);
  461.             if (procPtr == (Proc_ControlBlock *)NIL ||
  462.                 procPtr->machStatePtr == (Mach_State *)NIL) {
  463.                 Mach_MonPrintf("Bad process table index %d\n", 
  464.                     requestPtr->data);
  465.                 break;
  466.             }
  467.             }
  468.             debugStatePtr = &tmpDebugState;
  469.             bcopy((char *) procPtr->machStatePtr->switchRegState.regs,
  470.               (char *) tmpDebugState.regs, 32 * sizeof(int));
  471.             tmpDebugState.excPC = (unsigned)(Address)Mach_SwitchPoint;
  472.             dbgMaxStackAddr = (int)procPtr->machStatePtr->kernStackEnd;
  473.             signal = 2;
  474.         } else if (requestPtr->addr == (unsigned)-2) {
  475.             (void)Proc_Dump();
  476.         } else {
  477.             if (requestPtr->addr > sizeof(mach_DebugState) / 4) {
  478.             Mach_MonPrintf("Bogus UWRITE addr %x\n", requestPtr->addr);
  479.             replyPtr->status = 0;
  480.             } else {
  481.             replyPtr->data =
  482.                 *((int *)debugStatePtr + requestPtr->addr);
  483.             *((int *)debugStatePtr + requestPtr->addr) =
  484.                             requestPtr->data;
  485.             }
  486.         }
  487.         break;
  488.         }
  489.             case DBG_IREAD:
  490.             case DBG_DREAD:
  491.         if (Dbg_InRange(requestPtr->addr, 4, FALSE)) {
  492.             replyPtr->data = *(int *)requestPtr->addr;
  493.         } else {
  494.             replyPtr->status = 0;
  495.         }
  496.         break;
  497.             case DBG_IWRITE:
  498.         if (Dbg_InRange(requestPtr->addr, 4, TRUE)) {
  499.             replyPtr->data = *(int *)requestPtr->addr;
  500.             Mach_FlushCode((Address)requestPtr->addr, 4);
  501.             *(int *)requestPtr->addr = requestPtr->data;
  502.             Mach_EmptyWriteBuffer();
  503.         } else {
  504.             replyPtr->status = 0;
  505.         }
  506.         break;
  507.             case DBG_DWRITE:
  508.         if (Dbg_InRange(requestPtr->addr, 4, TRUE)) {
  509.             replyPtr->data = *(int *)requestPtr->addr;
  510.             *(int *)requestPtr->addr = requestPtr->data;
  511.         } else {
  512.             replyPtr->status = 0;
  513.         }
  514.         break;
  515.             case DBG_CONTP: 
  516.         dbg_BeingDebugged = TRUE;
  517.         done = TRUE;
  518.         break;
  519.             case DBG_SSTEP: {
  520.         unsigned        *pc;
  521.  
  522.         pc = DbgGetDestPC((Address)(debugStatePtr->excPC));
  523.         if (dbgTraceLevel >= 1) {
  524.             Mach_MonPrintf("Single-step PC=%x\n", pc);
  525.         }
  526.         if (!Dbg_InRange((unsigned int)pc, 4, TRUE)) {
  527.             Mach_MonPrintf("Bad SSTEP PC\n");
  528.             replyPtr->status = 0;
  529.             break;
  530.         }
  531.         sstepInst = *pc;
  532.         Mach_FlushCode((Address)pc, 4);
  533.         *pc = SSTEP_INST;
  534.         Mach_EmptyWriteBuffer();
  535.         dbg_BeingDebugged = TRUE;
  536.         done = TRUE;
  537.         break;
  538.         }
  539.             case DBG_PKILL:
  540.         break;
  541.             case DBG_DBREAD: 
  542.         if (Dbg_InRange(requestPtr->addr, 1, FALSE)) {
  543.             replyPtr->data = *(char *)requestPtr->addr;
  544.         } else {
  545.             replyPtr->status = 0;
  546.         }
  547.         break;
  548.             case DBG_DBWRITE:
  549.         if (Dbg_InRange(requestPtr->addr, 1, TRUE)) {
  550.             replyPtr->data = *(char *)requestPtr->addr;
  551.             *(char *)requestPtr->addr = requestPtr->data;
  552.         } else {
  553.             replyPtr->status = 0;
  554.         }
  555.         break;
  556.             case DBG_DHREAD:
  557.         if (Dbg_InRange(requestPtr->addr, 2, FALSE)) {
  558.             replyPtr->data = *(short *)requestPtr->addr;
  559.         } else {
  560.             replyPtr->status = 0;
  561.         }
  562.         break;
  563.             case DBG_DHWRITE:
  564.         if (Dbg_InRange(requestPtr->addr, 2, TRUE)) {
  565.             replyPtr->data = *(short *)requestPtr->addr;
  566.             *(short *)requestPtr->addr = requestPtr->data;
  567.         } else {
  568.             replyPtr->status = 0;
  569.         }
  570.         break;
  571.             case DBG_QUERY:
  572.         break;
  573.             case DBG_BEGINCALL:
  574.         break;
  575.             case DBG_ENDCALL:
  576.         break;
  577.             case DBG_DETACH:
  578.         dbg_BeingDebugged = FALSE;
  579.         done = TRUE;
  580.         Mach_MonPrintf("Sprite is now detached from the debugger\r\n");
  581.         break;
  582.             case DBG_GETMAXSTACK:
  583.         replyPtr->data = dbgMaxStackAddr;
  584.         break;
  585.             case DBG_GETSTATUS:
  586.         replyPtr->data = 0177 | (signal << 8);
  587.         break;
  588.         case DBG_GET_VERSION_STRING: {
  589.         char *version;
  590.         version = SpriteVersion();
  591.         strncpy(dataPtr, version, PACKET_DATA_SIZE);
  592.         dataSize = strlen(version) + 1 - 4;
  593.         break;
  594.         }
  595.         case DBG_REBOOT: {
  596.         char    *reboot;
  597.         reboot = (char *) &requestPtr->data;
  598.         Mach_MonReboot(reboot);
  599.         break;
  600.         }
  601.     }
  602.     SendReply(dataSize);
  603.     if (!done) {
  604.         (void)ReadRequest(FALSE);
  605.     }
  606.     }
  607. }
  608.